package com.yuyou.fn.balance.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.github.wens.framework.service.impl.SuperServiceImpl;
import com.github.wens.mybatisplus.examples.Example;
import com.github.wens.mybatisplus.plugins.Page;
import com.yuyou.fn.balance.entity.BalanceWithdrawal;
import com.yuyou.fn.balance.mapper.BalanceWithdrawalMapper;
import com.yuyou.fn.balance.service.IBalanceWithdrawalService;
import com.yuyou.fn.balance.vo.BalanceWithdrawalQueryVo;
import com.yuyou.fn.common.exception.BusException;
import com.yuyou.fn.common.util.BigDecimals;
import com.yuyou.fn.common.util.CriteriaUtils;
import com.yuyou.fn.common.util.Principals;
import com.yuyou.fn.common.util.TimeUtils;
import com.yuyou.fn.educational.entity.Campus;
import com.yuyou.fn.educational.entity.Student;
import com.yuyou.fn.educational.service.ICampusService;
import com.yuyou.fn.educational.service.IStudentService;
import com.yuyou.fn.settlement.entity.MainAccount;
import com.yuyou.fn.settlement.service.IMainAccountService;
import com.yuyou.fn.settlement.service.ISettlementService;
import org.redisson.Redisson;
import org.redisson.api.RLock;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.Arrays;
import java.util.List;

/**
 *
 * BalanceWithdrawal 表数据服务层接口实现类
 *
 */
@Service
public class BalanceWithdrawalServiceImpl extends SuperServiceImpl<BalanceWithdrawalMapper, BalanceWithdrawal,Long> implements IBalanceWithdrawalService {


    @Resource
    private ISettlementService settlementService;

    @Resource
    private ICampusService campusService;

    @Resource
    private IMainAccountService mainAccountService;

    @Resource
    private IStudentService studentService;

    @Resource
    private Redisson redisson ;

    @Transactional
    @Override
    public BalanceWithdrawal saveBalanceWithdrawal(Principals.Principal principal , Long applierMainAccountId, Long acceptCampusId, BigDecimal amount, String bankName, String bankCity, String cardUser, String cardNo, String reasonRemark) {
        RLock lock = redisson.getLock(String.format("mainAccountId:%s",applierMainAccountId ));
        if (lock.tryLock()) {
            try {
                if (amount.doubleValue()<=0d){
                    throw new BusException("输入的金额必须大于0");
                }
                BalanceWithdrawal balanceWithdrawal = new BalanceWithdrawal();
                balanceWithdrawal.setApplierMainAccountId(applierMainAccountId);
                balanceWithdrawal.setAcceptCampusId(acceptCampusId);
                balanceWithdrawal.setAmount(amount);
                balanceWithdrawal.setBankName(bankName);
                balanceWithdrawal.setBankCity(bankCity);
                balanceWithdrawal.setCardNo(cardNo);
                balanceWithdrawal.setCardUser(cardUser);
                balanceWithdrawal.setAcceptCampusId(acceptCampusId);
                balanceWithdrawal.setReasonRemark(reasonRemark);
                balanceWithdrawal.setOperatorId(principal.id);
                balanceWithdrawal.setOperatorName(principal.name);
                balanceWithdrawal.setStatus(0);
                balanceWithdrawal.setPayStatus(0);
                Campus campus = campusService.findById(acceptCampusId, "campusName" ,"areaTeamId");
                if(campus != null ){
                    balanceWithdrawal.setAcceptCampusName(campus.getCampusName());
                    balanceWithdrawal.setAreaTeamId(campus.getAreaTeamId());
                }
                MainAccount mainAccount = mainAccountService.findById(applierMainAccountId, "name" , "tag" , "balanceAmount");
                if(mainAccount == null ){
                    throw new IllegalArgumentException("Invalid applierMainAccountId");

                }

                if(BigDecimals.compare( amount , mainAccount.getBalanceAmount() ) > 0  ){
                    throw new BusException("提现金额大于账户余额");
                }


                balanceWithdrawal.setApplierMainAccountName(mainAccount.getName());
                balanceWithdrawal.setRemainAmount(mainAccount.getBalanceAmount().subtract(amount));


                JSONObject jsonObject = new JSONObject();
                if("student".equals(mainAccount.getTag())){
                    jsonObject = buildExtraStudent(applierMainAccountId);
                }
                balanceWithdrawal.setExtra(jsonObject.toJSONString());
                balanceWithdrawal.setCreateTime(TimeUtils.now());
                balanceWithdrawal.setUpdateTime(TimeUtils.now());



                insertSelective(balanceWithdrawal);

                settlementService.decreaseBalance(balanceWithdrawal.getApplierMainAccountId() , balanceWithdrawal.getAmount() , "提现");
                return balanceWithdrawal;


            } finally {
                lock.unlock();
            }
        }else{
            return null ;
        }


    }

    @Override
    public Page<BalanceWithdrawal> findBalanceWithdrawalByQuery(BalanceWithdrawalQueryVo balanceWithdrawalQueryVo, List<Long> campusIds , Integer pageNo , Integer pageSize ) {

        if(balanceWithdrawalQueryVo.getEndCreateTime() != null ){
            balanceWithdrawalQueryVo.setEndCreateTime(TimeUtils.changeOneDateLastTime(balanceWithdrawalQueryVo.getEndCreateTime()));
        }
        if(balanceWithdrawalQueryVo.getEndPayTime() != null ){
            balanceWithdrawalQueryVo.setEndPayTime(TimeUtils.changeOneDateLastTime(balanceWithdrawalQueryVo.getEndPayTime()));
        }
        if(balanceWithdrawalQueryVo.getEndAuditTime() != null ){
            balanceWithdrawalQueryVo.setEndAuditTime(TimeUtils.changeOneDateLastTime(balanceWithdrawalQueryVo.getEndAuditTime()));
        }


        Example<BalanceWithdrawal> example = BalanceWithdrawal.createExample();
        Example.Criteria criteria = example.createCriteria();
        CriteriaUtils.fillCondition(criteria,balanceWithdrawalQueryVo);
        criteria.andIn("acceptCampusId" , campusIds );
        if(campusIds == null || campusIds.size() == 0 ){
            criteria.andEqualTo("acceptCampusId" , 0l ); // not exist
        }
        example.orderBy("createTime").desc();

        return findPageByExample(example,pageNo , pageSize );
    }

    @Override
    public Long countBalanceWithdrawalByQuery(BalanceWithdrawalQueryVo balanceWithdrawalQueryVo, List<Long> campusIds) {
        if(balanceWithdrawalQueryVo.getEndCreateTime() != null ){
            balanceWithdrawalQueryVo.setEndCreateTime(TimeUtils.changeOneDateLastTime(balanceWithdrawalQueryVo.getEndCreateTime()));
        }
        if(balanceWithdrawalQueryVo.getEndPayTime() != null ){
            balanceWithdrawalQueryVo.setEndPayTime(TimeUtils.changeOneDateLastTime(balanceWithdrawalQueryVo.getEndPayTime()));
        }
        if(balanceWithdrawalQueryVo.getEndAuditTime() != null ){
            balanceWithdrawalQueryVo.setEndAuditTime(TimeUtils.changeOneDateLastTime(balanceWithdrawalQueryVo.getEndAuditTime()));
        }


        Example<BalanceWithdrawal> example = BalanceWithdrawal.createExample();
        Example.Criteria criteria = example.createCriteria();
        CriteriaUtils.fillCondition(criteria,balanceWithdrawalQueryVo);
        criteria.andIn("acceptCampusId" , campusIds );
        if(campusIds == null || campusIds.size() == 0 ){
            criteria.andEqualTo("acceptCampusId" , 0l ); // not exist
        }
        //example.orderBy("createTime").desc();

        return countByExample(example);
    }

    @Override
    public void audit(Long balanceWithdrawalId, Integer status ,String auditRemark, Principals.Principal principal) {

        if(!Arrays.asList(1,2).contains(status)){
            throw new IllegalArgumentException("Invalid status");
        }

        if(principal.id.equals(findById(balanceWithdrawalId,"operatorId").getOperatorId())){
            throw new BusException("很抱歉，您无法审批自己发起的申请！");
        }

        BalanceWithdrawal balanceWithdrawal  = new BalanceWithdrawal() ;
        balanceWithdrawal.setStatus(status);
        balanceWithdrawal.setAuditRemark(auditRemark);
        balanceWithdrawal.setAuditId(principal.id);
        balanceWithdrawal.setAuditName(principal.name);
        balanceWithdrawal.setAuditTime(TimeUtils.now());
        Example<BalanceWithdrawal> example = BalanceWithdrawal.createExample();
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo("balanceWithdrawalId" ,balanceWithdrawalId);
        criteria.andEqualTo("status" , 0 );

        if(updateSelectiveByExample(balanceWithdrawal ,example ) && status == 2 ){
            BalanceWithdrawal withdrawal = findById(balanceWithdrawalId);
            settlementService.increaseBalance(withdrawal.getApplierMainAccountId() , withdrawal.getAmount(), "提现审核失败，余额退回");
        }

    }

    @Override
    public void setupPayStatus(Long[] balanceWithdrawalIds, Principals.Principal principal) {

        BalanceWithdrawal balanceWithdrawal  = new BalanceWithdrawal() ;
        balanceWithdrawal.setPayStatus(1);
        balanceWithdrawal.setPayPersonId(principal.id);
        balanceWithdrawal.setPayPersonName(principal.name);
        balanceWithdrawal.setPayTime(TimeUtils.now());
        Example<BalanceWithdrawal> example = BalanceWithdrawal.createExample();
        Example.Criteria criteria = example.createCriteria();
        criteria.andIn("balanceWithdrawalId" ,Arrays.asList(balanceWithdrawalIds));
        criteria.andEqualTo("status" , 1 );
        updateSelectiveByExample(balanceWithdrawal ,example );

    }

    private JSONObject buildExtraStudent(Long studentId) {
        JSONObject jsonObject = new JSONObject();
        Student student = studentService.findById(studentId);
        jsonObject.put("tag" ,"student");
        jsonObject.put("studentNo",student.getStudentNo());
        jsonObject.put("name",student.getName());
        jsonObject.put("phoneNo",student.getPhoneNo());
        jsonObject.put("gradeName",student.getGradeName());
        jsonObject.put("school",student.getSchool());
        return jsonObject ;
    }


}